package Entity;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Queue;

import com.sun.org.apache.bcel.internal.generic.Type;

import Controllers.GlobalData;
import Controllers.Notificator;
import Controllers.GenericToolsForController.PDFfile;
import Controllers.GenericToolsForController.RequestMainStatusEnum;
import Controllers.GenericToolsForController.RequestStepStatusEnum;
import Controllers.GenericToolsForController.WorkerPostion;
import Controllers.GenericToolsForController.WorkerRolls;
import Exception.ICMException;

public class Request implements Serializable 
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	////////////////////////////
	private int requestId;
	
	private String currentState; // the current state of the system
	private String description;  // the description of the requested change 
	private String execuse;     // the execuse for this request
	
	private Date dayOfCreation;

	private String notes;
	private PDFfile file;
	private InfoSystem infoSystem; 
	////////////////////////////
	
	
	////////////////////////////
	private RequestStatusHistory currentStatus;
	private String proposedChange; // The initiator needs to enter what change he propose to make
	private String explanation; //    and explanation why he needs the change.
	////////////////////////////
	
	
	////////////////////////////
	private List<RequestStatusHistory> history;

	////////////////////////////
	

	/////////////////////////////
	private int timeForEvaluation;
	private int timeForReview;
	private int timetimeForExecution;
	private int timeForTesting;
	////////////////////////////
	
	
	////////////////////////////
	private Worker inspector;
	private Worker evaluator;
	private Worker executionLeader;
	private Worker cometteMembers1; // 2 comette Members
	private Worker cometteMembers2; // 2 comette Members
	private Worker chairman;
	private Worker examiner;
	private User initiator;
	////////////////////////////
	
	
	////////////////////////////			
	private Report testFailureReport;
	private Report evaluationReport;

	private String propsedChange;	
	////////////////////////////
	
	

	//////////////////////////////////////////////////////////////
	public RequestStatusHistory getCurrentStatus() 
	{
		return currentStatus;
	}

	public void  setCurrentStatus(RequestStatusHistory cureentStatus) 
	{
		this.currentStatus = cureentStatus;
	}
    //////////////////////////////////////////////////////////////	
	
	
    //////////////////////////////////////////////////////////////	
	public int getTimeForEvaluation() 
	{
		return timeForEvaluation;
	}
	public void setTimeForEvaluation(int timeForEvaluation) 
	{
		this.timeForEvaluation = timeForEvaluation;
	}
	public int getTimeForReview() 
	{
		return timeForReview;
	}
	public void setTimeForReview(int timeForReview) 
	{
		this.timeForReview = timeForReview;
	}
	public int getTimetimeForExecution() 
	{
		return timetimeForExecution;
	}
	public void setTimetimeForExecution(int timetimeForExecution) 
	{
		this.timetimeForExecution = timetimeForExecution;
	}
	public int getTimeForTesting()
	{
		return timeForTesting;
	}
	public void setTimeForTesting(int timeForTesting) 
	{
		this.timeForTesting = timeForTesting;
	}
    //////////////////////////////////////////////////////////////
	
	public Date getDayOfCreation() {
		return dayOfCreation;
	}

	public void setDayOfCreation(Date dayOfCreation) {
		this.dayOfCreation = dayOfCreation;
	}

	public String getPropsedChange() {
		return propsedChange;
	}

	public void setPropsedChange(String propsedChange) {
		this.propsedChange = propsedChange;
	}
	
	
    //////////////////////////////////////////////////////////////	
	public InfoSystem getInfoSystem() 
	{
		return infoSystem;
	}
	public void setInfoSystem(InfoSystem infoSystem) 
	{
		this.infoSystem = infoSystem;
	}
	public String getNotes() 
	{
		return notes;
	}
	public void setNotes(String notes) 
	{
		this.notes = notes;
	}
	public PDFfile getFile() 
	{
		return file;
	}
	public void setFile(PDFfile file) 
	{
		this.file = file;
	}
    //////////////////////////////////////////////////////////////	
	
	
	
	
    //////////////////////////////////////////////////////////////	
	public Worker getInspector() 
	{
		return inspector;
	}
	public void setInspector(Worker inspector) 
	{
		this.inspector = inspector;
	}
	public Worker getEvaluator() 
	{
		return evaluator;
	}
	public void setEvaluator(Worker evaluator) 
	{
		this.evaluator = evaluator;
	}
	public Worker getExecutionLeader() 
	{
		return executionLeader;
	}
	public void setExecutionLeader(Worker executionLeader) 
	{
		this.executionLeader = executionLeader;
	}
	public Worker getCometteMembers1() 
	{
		return cometteMembers1;
	}
	public void setCometteMembers1(Worker cometteMembers1) 
	{
		this.cometteMembers1 = cometteMembers1;
	}
	public Worker getCometteMembers2() 
	{
		return cometteMembers2;
	}
	public void setCometteMembers2(Worker cometteMembers2) 
	{
		this.cometteMembers2 = cometteMembers2;
	}
	public Worker getChairman() 
	{
		return chairman;
	}
	public void setChairman(Worker chairman) 
	{
		this.chairman = chairman;
	}
	public Worker getExaminer()
	{
		return examiner;
	}
	public void setExaminer(Worker examiner) 
	{
		this.examiner = examiner;
	}
	public User getInitiator() 
	{
		return initiator;
	}
	public void setInitiator(User initiator) 
	{
		this.initiator = initiator;
	}
    //////////////////////////////////////////////////////////////	

	
	
	
	
	
	
	
	/**
	 *  constructor
	 * @param requestId
	 * @param description
	 * @param date
	 * @param notes
	 * @param file
	 * @param infoSystem
	 * @param cureentStatus
	 * @param inspector
	 * @param evaluator
	 * @param executionLeader
	 * @param cometteMembers1
	 * @param cometteMembers2
	 * @param chairman
	 * @param examiner
	 * @param initiator
	 * @param proposed_change
	 * @param currentState
	 * @param execuse
	 */
	public Request(int requestId, String description, Date date, String notes,
			PDFfile file, InfoSystem infoSystem,
			RequestStatusHistory cureentStatus, Worker inspector,
			Worker evaluator, Worker executionLeader, Worker cometteMembers1,
			Worker cometteMembers2, Worker chairman, Worker examiner,
			User initiator,String proposed_change,String currentState,String execuse) {
		super();
		this.requestId = requestId;
		this.description = description;
		this.dayOfCreation = date;
		this.notes = notes;
		this.file = file;
		this.infoSystem = infoSystem;
		this.currentStatus = cureentStatus;
		this.inspector = inspector;
		this.evaluator = evaluator;
		this.executionLeader = executionLeader;
		this.cometteMembers1 = cometteMembers1;
		this.cometteMembers2 = cometteMembers2;
		this.chairman = chairman;
		this.examiner = examiner;
		this.initiator = initiator;
		this.propsedChange = proposed_change;
		this.currentState = currentState;
		this.execuse = execuse;
	}
	/**
	 *  another constructor
	 * @param requestId
	 * @param description
	 * @param date
	 * @param notes
	 * @param file
	 * @param infoSystem
	 * @param cureentStatus
	 * @param inspector
	 * @param evaluator
	 * @param executionLeader
	 * @param cometteMembers1
	 * @param cometteMembers2
	 * @param chairman
	 * @param examiner
	 * @param initiator
	 */
	public Request(int requestId, String description, Date date, String notes,
			PDFfile file, InfoSystem infoSystem,
			RequestStatusHistory cureentStatus, Worker inspector,
			Worker evaluator, Worker executionLeader, Worker cometteMembers1,
			Worker cometteMembers2, Worker chairman, Worker examiner,
			User initiator) {
		super();
		this.requestId = requestId;
		this.description = description;
		this.dayOfCreation = date;
		this.notes = notes;
		this.file = file;
		this.infoSystem = infoSystem;
		this.currentStatus = cureentStatus;
		this.inspector = inspector;
		this.evaluator = evaluator;
		this.executionLeader = executionLeader;
		this.cometteMembers1 = cometteMembers1;
		this.cometteMembers2 = cometteMembers2;
		this.chairman = chairman;
		this.examiner = examiner;
		this.initiator = initiator;
		
	}
	
	
	public Request(){}



	public int getRequestId() {
		return requestId;
	}

	public void setRequestId(int requestId) {
		this.requestId = requestId;
	}

	public String getCurrentState() {
		return currentState;
	}

	public void setCurrentState(String currentState) {
		this.currentState = currentState;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getExecuse() {
		return execuse;
	}

	public void setExecuse(String execuse) {
		this.execuse = execuse;
	}

	public Date getDate() {
		return dayOfCreation;
	}

	public void setDate(Date date) {
		this.dayOfCreation = date;
	}

	public String getProposedChange() {
		return proposedChange;
	}

	public void setProposedChange(String proposedChange) {
		this.proposedChange = proposedChange;
	}

	public String getExplanation() {
		return explanation;
	}

	public void setExplanation(String explanation) {
		this.explanation = explanation;
	}

	public List<RequestStatusHistory> getHistory() {
		return history;
	}

	public void setHistory(List<RequestStatusHistory> history) {
		this.history = history;
	}

	public Report getTestFailureReport() {
		return testFailureReport;
	}

	public void setTestFailureReport(Report testFailureReport) {
		this.testFailureReport = testFailureReport;
	}

	public Report getEvaluationReport() {
		return evaluationReport;
	}

	public void setEvaluationReport(Report evaluationReport) {
		this.evaluationReport = evaluationReport;
	}
/**
 * constructor
 * @param currentState
 * @param changeDescription
 * @param execuse
 * @param infoSys
 * @param note
 * @param file2
 * @param init
 */
	public Request(String currentState, String changeDescription,
			String execuse, InfoSystem infoSys, String note, PDFfile file2,User init) {
		this.description = changeDescription;
		this.currentState = currentState;
		this.execuse = execuse;
		this.infoSystem = infoSys;
		this.notes = note;
		this.file = file2;
		this.initiator = init;
	}
	

	/**
	 * constructor
	 * @param id
	 * @param infoSystem
	 * @param date
	 * @param desc
	 */
	public Request(int id, InfoSystem infoSystem, java.sql.Date date,String desc) {
		// TODO Auto-generated constructor stub
		this.requestId = id;
		this.infoSystem = infoSystem;
		this.dayOfCreation = date;
		this.description = desc;
	}

	private int addInitHistory()
	{
		//TODO implement
		return 0;
	}
	
	public boolean setTimeForExecution(int time)
	{
		String rowId = this.getRequestId() + "";
		String varame = "timeForExecution";
		String value = time + "";
		String[] arr = new String[]{rowId,varame,value};
		
		Message msg = new Message(7029, GlobalData.MESSAGE_ID(), arr);
        
		Message AnswerMessage = null;
		System.out.println("Request - addRequestToDB : Try to Add new info ");
		try 
		{
			GlobalData.client.sendToServer(msg);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			while (true)
			{
				if (GlobalData.client.isRecivedMessage()==true)
				{
					AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
				    if (AnswerMessage!=null)
				  	      break;
				}	
			}
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean )
		    return  ((Boolean)AnswerMessage.getDataGram());
		return false;
	}
	/**
	 * adding request to db server side opreation
	 * opcode 7003
	 * @return
	 */
	public int addNewRequestToDB()
	{
		
		Message msg = new Message(7003, GlobalData.MESSAGE_ID(), this);
        
		Message AnswerMessage = null;
		System.out.println("Request - addRequestToDB : Try to Add new info ");
		try 
		{
			GlobalData.client.sendToServer(msg);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			while (true)
			{
				if (GlobalData.client.isRecivedMessage()==true)
				{
					AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
				    if (AnswerMessage!=null)
				  	      break;
				}	
			}
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Request - addRequestToDB : Add new Request ");
		if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Integer )
		    return  ((Integer)AnswerMessage.getDataGram()).intValue();
		return -1;
	}
	/**
	 * resume requests opcode 7011
	 * @param op TODO
	 * @return
	 */
	public boolean resume(int op)
	{
		if (op==0)
		{
			int okFlag=0;
			Status[] stats= new Status[1];
			stats[0] = new Status(null, RequestMainStatusEnum.SUSPEND);
			
			for(int i=0; i<stats.length ; i++)
			{
				if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() 
						)
					okFlag = 1;
			}
			if(okFlag == 0)
				return false;
			//Check if the inspector is nominate to this request
			if(WorkerRolls.ICM_MANGER != GlobalData.worker.getRole())
				return false;	
			return true;	
			
		}
		else
		if (op==1)
		{
		Message msg = new Message(7011, GlobalData.MESSAGE_ID(), this);
        
		Message AnswerMessage = null;
		System.out.println("Request - resume : Try to resume Request ");
		try 
		{
			GlobalData.client.sendToServer(msg);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			while (true)
			{
				if (GlobalData.client.isRecivedMessage()==true)
				{
					AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
				    if (AnswerMessage!=null)
				  	      break;
				}	
			}
		}
		
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(" Request - resume : Try to resume Request ");
		if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean )
		    return  ((Boolean)AnswerMessage.getDataGram());
		return false;
		}
		return false;
		
	}
	/**
	 * suspend request opcode 7012
	 * @return
	 */
	public boolean suspend(int i)
	{
		if(i == 1)
		{
			Message msg = new Message(7012, GlobalData.MESSAGE_ID(), this);
	        
			Message AnswerMessage = null;
			System.out.println("Request - resume : Try to resume Request ");
			try 
			{
				GlobalData.client.sendToServer(msg);
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				while (true)
				{
					if (GlobalData.client.isRecivedMessage()==true)
					{
						AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
					    if (AnswerMessage!=null)
					  	      break;
					}	
				}
			} 
			catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(" Request - suspend : Try to suspend Request ");
			if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean )
			    return  ((Boolean)AnswerMessage.getDataGram());
			return false;
		}
		else if(i == 0)
		{
			//Check if the Ststus is OK
			if(getCurrentStatus().getStatus().getmStatus() != RequestMainStatusEnum.OPEN )
				return false;

			//Check if the inspector is nominate to this request
			if(inspector.getId() != GlobalData.worker.getId())
				return false;
			
			Status status = new Status(this.getCurrentStatus().getStatus().getsStatus(), RequestMainStatusEnum.SUSPEND); 
			RequestStatusHistory cureentStatus = new RequestStatusHistory(4, status, new Date(), new Date(), null, null, null);
			
			return true;
			
		}
		return false;
	}
/**
 * close request opcode: 7015
 * server side opreation
 * 
 * @return
 */
	public boolean close(int op)
	{
		if(op == 1)
		{
			Message msg = new Message(7015, GlobalData.MESSAGE_ID(), new Integer(getRequestId()));
			Message AnswerMessage = null;
			try 
			{
				GlobalData.client.sendToServer(msg);
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				while (true)
				{
					if (GlobalData.client.isRecivedMessage()==true)
					{
						AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
					    if (AnswerMessage!=null)
					  	      break;
					}	
				}
			} 
			catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean )
			    return  ((Boolean)AnswerMessage.getDataGram());
			return false;
		}
		else if(op == 0 )
		{
			//Check if the Ststus is OK
			int okFlag=0;
			Status[] stats= new Status[2];
			stats[0] = new Status(RequestStepStatusEnum.REV_REVIEWED_CLOSE, RequestMainStatusEnum.OPEN);
			stats[1] = new Status(RequestStepStatusEnum.TST_PASSED, RequestMainStatusEnum.OPEN);
			for(int i=0; i<stats.length ; i++)
			{
				if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
						getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
					okFlag = 1;
			}
			if(okFlag == 0)
				return false;
			
			//Check if the inspector is nominate to this request
			if(inspector.getId() != GlobalData.worker.getId())
				return false;
			
			/*RequestStepStatusEnum old = this.getCurrentStatus().getStatus().getsStatus();
			String mailToSend;
			User init = this.getInitiator();
			if(old == RequestStepStatusEnum.TST_PASSED)
			{
				mailToSend = "Dear " + init.getFirstName() + " " + init.getLastName() + ",\n " + 
						     "Your Requests number " + this.getRequestId() + " the required change has been made.\n " +
						     "Sincerly yours ICM staff.";
			}
			else // old == RequestStepStatusEnum.REV_REVIEWED_CLOSE)
			{
				mailToSend = "Dear " + init.getFirstName() + " " + init.getLastName() + ",\n " + 
					     "Your Requests number " + this.getRequestId() + " the required change has been denied.\n " +
					     "Sincerly yours ICM staff.";
			}
			Notificator.sendEmailNotification(this.getInitiator().getEmail(),mailToSend);
			*/
			return true;
			

		}
		return false;
	}
	
	
	
	/**
	 * sort history request
	 */
	public void sortHistory()
	{
		//private List<RequestStatusHistory> history;
		List<RequestStatusHistory> sorted = new ArrayList<RequestStatusHistory>();
		RequestStatusHistory first=null;
		RequestStatusHistory prev=null;

		//find the first history
		for(RequestStatusHistory his : history)
		{
			if(his.getPrevHistory()==0)
			{
				first = his;
				break;
			}
		}
		sorted.add(first);
		
		prev = first;
		while(prev.getNextHistory()==0)
		{
			for(RequestStatusHistory his : history)
			{
				if(his.getPrevHistory()==prev.getNextHistory())
				{
					sorted.add(his);
					prev = his;
					break;
				}
			}
		}
		history = sorted;
		 
		//OR
		/*RequestStatusHistory[] a = null;
		history.toArray(a);
		quickSort(a,0,a.length-1);
		history = stringToList(a);*/
	}
	
	
	
	//quickSort to the  List<RequestStatusHistory>
	/**
	 * 
	 * @param requestshistory[] a
	 * @return
	 */
	public List<RequestStatusHistory> stringToList(RequestStatusHistory[] a)
	{
		List<RequestStatusHistory> list = new ArrayList<RequestStatusHistory>();
		for(int i=0;i<a.length;i++)
		{
			list.add(a[i]);
		}
		return list;
	}
	/**
	 *  quick sort 
	 * @param a
	 * @param p
	 * @param r
	 */
	public void quickSort(RequestStatusHistory[] a, int p, int r)
    {
        if(p<r)
        {
            int q=partition(a,p,r);
            quickSort(a,p,q);
            quickSort(a,q+1,r);
        }
    }
	/**
	 * partion of quicksort implemnation
	 * @param a
	 * @param p
	 * @param r
	 * @return
	 */
    private  int partition(RequestStatusHistory[] a, int p, int r) {

    	int x = a[p].getHistoryId();
        int i = p-1 ;
        int j = r+1 ;

        while (true) {
            i++;
            while ( i< r && a[i].getHistoryId() < x)
                i++;
            j--;
            while (j>p && a[j].getHistoryId() > x)
                j--;

            if (i < j)
                swap(a, i, j);
            else
                return j;
        }
    }
    /**
     * swap method
     * @param a
     * @param i
     * @param j
     */
    private void swap(RequestStatusHistory[] a, int i, int j)
    {
    	RequestStatusHistory temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
	
    /**
     * asks for more time
     * @param days
     * @param reason
     * @return
     */
	public boolean ackForMoreTime(int days,String reason,int op) 
	{
		if (op==1){
		Object[] prams = new Object[3];
		prams[0] = this;
		prams[1] =  new Integer(days);
		prams[2] = reason;
				
		Message msg = new Message(7020, GlobalData.MESSAGE_ID(),prams);
		Message AnswerMessage = null;
		try 
		{
			GlobalData.client.sendToServer(msg);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			while (true)
			{
				if (GlobalData.client.isRecivedMessage()==true)
				{
					AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
				    if (AnswerMessage!=null)
				  	      break;
				}	
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean )
		    return  ((Boolean)AnswerMessage.getDataGram());
		return false;
		}
		else if (op==0)
			{
		
			
			// if return false = if in each step the responsible for the step isn't the one who ask for more time
			
			if ((this.isInEvluation() && this.getEvaluator()!=GlobalData.worker) ||
					   (this.isInReviewAndDecision() && this.getChairman()!=GlobalData.worker) ||
					   (this.isInExecuation() && this.getExecutionLeader()!=GlobalData.worker) ||
					   (this.isInTesting() && this.getExaminer()!=GlobalData.worker))            
						return false;
			
			//if return false =if the request is in close step
			if (this.isInClose())
				return false;
			
			//if return false =if the request is waiting for time extension
			if ((this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.EVL_EVLUATION_TIME_EXTENSION_PENDING)||
					   (this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_PENDING)||
					   (this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.EXE_UNEXECUTED_TIME_EXTENSION_PENDING)||
					   (this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.TST_UTESTED_TIME_EXTENSION_PENDING)||
					   (this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.REV_REVIEWED_TIME_EXTENSION_PENDING))
						return false;
			

			//if return false =if the request is not open
			if (this.getCurrentStatus().getStatus().getmStatus()!=RequestMainStatusEnum.OPEN)
				return false;
			
			
			
			//if the request has already got time extension to the current step
			
			String startWhit = this.getCurrentStatus().getStatus().getsStatus().toString().substring(0, 3); // get the first 3 letter of the step status
			String endWhit = "EXTENDED"; // if the current step is Already Extended, there is a step status that end whit "EXTENDED"
			for(RequestStatusHistory his : this.getHistory())
			{
				if(his.getStatus().getsStatus().toString().startsWith(startWhit) &&
						his.getStatus().getsStatus().toString().endsWith(endWhit) )
					return false;
			}
			
			// check If There Is Less Then Three Days To Current Step
			Date now = new Date();
			Date dueDaye = this.getCurrentStatus().getDueDate();
			float dayLeft = (float) ((dueDaye.getTime() - now.getTime())/(1000.0*24.0*60.0*60.0));
			if(dayLeft > 3 || dayLeft<0)
				  return false;
			
			//if return false =if the request is in EVL_UNVALUATED_WITH_TIME sStatus and step days till due <3
			
			//if ((dayLeft <3) && (this.getCurrentStatus().getStatus().getsStatus()==RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME))
			//	return false;

			
		return true;
		}	
			
	return false;
	}
    
/*	public static void main(String [ ] args)
	{
		
		ArrayList<RequestStatusHistory> history;
		Request req;
		
		ArrayList<Request> requestsList;
		requestsList = new ArrayList<Request>();
		
		Worker evaluator_62,evaluator_2;   // can be examiner/chairman etc. specifically we want to check about EVL step 
		evaluator_62 = new Worker(1, 62, "shimon", "Arzuan", "icmbraudesys@gmail.com", "0508-1234567", "shimon1171", "2" );
		evaluator_2 = new Worker(2, 2, "guy", "peleg", "icmbraudesys@gmail.com", "0508-1234567", "guyp", "2" );
		User initiator = new User(3, "Ron", "Rosesnfeld","icmbraudesys@gmail.com", "0508-1234567", "roon", "Student");		

		//the current worker that log to the system
		GlobalData.worker = evaluator_62;
		
		
		
		req = new Request();
		req.setRequestId(22);
		req.setEvaluator(evaluator_62);
		req.setInitiator(initiator);
		Status status = new Status(RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME, RequestMainStatusEnum.OPEN); 
		
		Date sDate = new Date(); 
		Date dDate;
		Calendar cal = Calendar.getInstance(); 
		cal = Calendar.getInstance();  
		cal.setTime(sDate);  
		cal.add(Calendar.DATE, 2); // add 2 days   
		dDate = cal.getTime(); 
		
		RequestStatusHistory  cureentStatus = new RequestStatusHistory(2, status, sDate , dDate , null, null, null);
		req.setCurrentStatus(cureentStatus);
		history = new ArrayList<RequestStatusHistory>();
		history.add(cureentStatus);
		req.setHistory(history);
		requestsList.add(req);
		
		
		for(Request req1 : requestsList)
		{
				
			   System.out.println(req.requestId+": ");
			   System.out.println(req1.ackForMoreTime(3,"bla bla", 0));  
			   
		}
		
		
		
		
	}
	
	*/
	
   
	/**
	 * extends time to requests
	 * @param newStatus
	 * @param commentToHistory
	 */
	public void extendTime(Status newStatus , String commentToHistory) 
	{
		int dayOfStep =(int) (this.getCurrentStatus().getDueDate().getTime() - this.getCurrentStatus().getStartDate().getTime())/(1000*24*60*60) ; 
		changeStatus( newStatus,commentToHistory,dayOfStep);
	}
	public void denyTimeExtension(Status newStatus , String commentToHistory)
	{
		int dayOfStep=0;
		int prevId = this.getCurrentStatus().getPrevHistory();
		RequestStatusHistory rh = getHistory(prevId);
		if(rh!=null)
		{
			dayOfStep = (int)(rh.getDueDate().getTime() - rh.getFinishDate().getTime())/(1000*24*60*60) ; 
		}
		changeStatus( newStatus,commentToHistory,dayOfStep);
	}
	public void denyTimeToStep(Status newStatus , String commentToHistory)
	{
		int dayOfStep=0;
		changeStatus( newStatus,commentToHistory,dayOfStep);
	}
	
	/**
	 * get history by id
	 * @param id
	 * @return
	 */
	public RequestStatusHistory getHistory(int id)
	{
		for(RequestStatusHistory rh : this.getHistory())
		{
			if(rh.getHistoryId() == id)
				return rh;
		}
		return null;
	}
	
	public boolean reviewApproved(){
		
		//Check if the Ststus is OK
				int okFlag=0;
				Status[] stats= new Status[1];
				stats[0] = new Status(RequestStepStatusEnum.EVL_PASSED, RequestMainStatusEnum.OPEN);
				
				for(int i=0; i<stats.length ; i++)
				{
					if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
							getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
						okFlag = 1;
				}
				if(okFlag == 0)
					return false;
				
				//Check if the chairman is nominate to this request
				if(chairman.getId() != GlobalData.worker.getId())
					return false;
				
		return true;
				
	}
	public boolean reviewDenied(){
		
		//Check if the Ststus is OK
				int okFlag=0;
				Status[] stats= new Status[1];
				stats[0] = new Status(RequestStepStatusEnum.EVL_PASSED, RequestMainStatusEnum.OPEN);
				
				for(int i=0; i<stats.length ; i++)
				{
					if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
							getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
						okFlag = 1;
				}
				if(okFlag == 0)
					return false;
				
				//Check if the chairman is nominate to this request
				if(chairman.getId() != GlobalData.worker.getId())
					return false;
				return true;
				
				
	}
	public boolean moreDetailsNeeded(){
			
		//Check if the Ststus is OK
		int okFlag=0;
		Status[] stats= new Status[1];
		stats[0] = new Status(RequestStepStatusEnum.EVL_PASSED, RequestMainStatusEnum.OPEN);
		
		for(int i=0; i<stats.length ; i++)
		{
			if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
					getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
				okFlag = 1;
		}
		if(okFlag == 0)
			return false;
		
		//Check if the chairman is nominate to this request
		if(chairman.getId() != GlobalData.worker.getId())
			return false;
		
		return true;
	}
	
	
	public boolean testPass(){
		
		//Check if the Status is OK
		int okFlag=0;
		Status[] stats= new Status[1];
		stats[0] = new Status(RequestStepStatusEnum.EXE_PASSED, RequestMainStatusEnum.OPEN);
		
		for(int i=0; i<stats.length ; i++)
		{
			if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
					getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
				okFlag = 1;
		}
		if(okFlag == 0)
			return false;
		if (this.getCurrentStatus().getDueDate()==null)
			return false;
		//Check if the inspector is nominate to this request
		if(examiner.getId() != GlobalData.worker.getId())
			return false;	
		return true;	
	}
	
	public boolean testFaile(int timeforexecution){
		
		//Check if the Ststus is OK
		int okFlag=0;
		Status[] stats= new Status[1];
		stats[0] = new Status(RequestStepStatusEnum.EXE_PASSED, RequestMainStatusEnum.OPEN);
		
		for(int i=0; i<stats.length ; i++)
		{
			if(getCurrentStatus().getStatus().getmStatus() == stats[i].getmStatus() &&
					getCurrentStatus().getStatus().getsStatus() == stats[i].getsStatus())
				okFlag = 1;
		}
		if(okFlag == 0)
			return false;
		if (this.getCurrentStatus().getDueDate()==null)
			return false;
		//Check if the inspector is nominate to this request
		if(examiner.getId() != GlobalData.worker.getId())
			return false;
		
		
		
	
		
		return true;
		
		
	}
	
	/**
	 *  change status to request
	 * @param newStatus
	 * @param commentToHistory
	 * @param dayOfStep
	 */
	public void changeStatus(Status newStatus,String commentToHistory,int dayOfStep)
	{
		Message msg= null;
		Message AnswerMessage= null;
		Object[] datagarm = new Object[] {new Integer(requestId),newStatus, commentToHistory, new Integer(dayOfStep)};
		 msg = new Message(7028, GlobalData.MESSAGE_ID(),datagarm);
			try 
			{
				if (msg != null)
		    	{
		       		System.out.println("msg sent");
					GlobalData.client.sendToServer(msg);
					}
					try {
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					while (true)
					{
						if (GlobalData.client.isRecivedMessage()==true)
						{
							AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
						    if (AnswerMessage!=null)
						  	      break;
						}	
					}
					
				} 
				catch (Exception e) 
				{
					e.printStackTrace();
				}
				System.out.println("request finished updating, check db for results");
	}
/**
 * add report to db
 * @param report
 * @return
 * @throws ICMException
 */
	public boolean addReport(Report report) throws ICMException
	{
		try
		{
		int entry = report.addToDb();
		if (entry > 0 )
		{
			report.setReportId(entry);
			if (connectReport(report))
			{
				return true;
			}
			else
			{
				throw new ICMException("could not connect report to request");
			}
		
		}
		else
		{
		 throw new ICMException("Could not create new report");	
		}
	
		}
		finally{}
	}
		
	/**
	 *  connect report to request
	 * @param report
	 * @return
	 */
	public boolean connectReport(Report report) 
		{	
		int reportId = report.getReportId();
		Message  msg = null;
		Message	 AnswerMessage = null;
		Object[] datagarm = new Object[] {new Integer(reportId),this};
		msg = new Message(7018, GlobalData.MESSAGE_ID(),datagarm);
			try 
			{
				if (msg != null)
		    	{
		       		System.out.println("msg sent");
					GlobalData.client.sendToServer(msg);
					}
					try {
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					while (true)
					{
						if (GlobalData.client.isRecivedMessage()==true)
						{
							AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
						    if (AnswerMessage!=null)
						  	      break;
						}	
					}
					
				} 
				catch (Exception e) 
				{
					e.printStackTrace();
				}
				System.out.println("HERE!");
				if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean  )
				{
					return (Boolean)AnswerMessage.getDataGram();
				}
				return false;

			}  
	
	
	public boolean addTestingReport(Report report) throws ICMException
	{
		try
		{
		int entry = report.addToDb();
		if (entry > 0 )
		{
			report.setReportId(entry);
			if (connectTestingFailureReport(report))
			{
				return true;
			}
			else
			{
				throw new ICMException("could not connect report to request");
			}
		
		}
		else
		{
		 throw new ICMException("Could not create new report");	
		}
	
		}
		finally{}
	}
	

	public boolean connectTestingFailureReport(Report report) 
	{	
	int reportId = report.getReportId();
	Message  msg = null;
	Message	 AnswerMessage = null;
	Object[] datagarm = new Object[] {new Integer(reportId),this};
	msg = new Message(7019, GlobalData.MESSAGE_ID(),datagarm);
		try 
		{
			if (msg != null)
	    	{
	       		System.out.println("msg sent");
				GlobalData.client.sendToServer(msg);
				}
				try {
					Thread.sleep(500);
				} catch (Exception e) {
					e.printStackTrace();
				}
				while (true)
				{
					if (GlobalData.client.isRecivedMessage()==true)
					{
						AnswerMessage = GlobalData.client.getAnsweredMessage(msg);
					    if (AnswerMessage!=null)
					  	      break;
					}	
				}
				
			} 
			catch (Exception e) 
			{
				e.printStackTrace();
			}
			System.out.println("HERE!");
			if(AnswerMessage.getDataGram()!=null && AnswerMessage.getDataGram() instanceof Boolean  )
			{
				return (Boolean)AnswerMessage.getDataGram();
			}
			return false;

		}  
		
	/**
	 * string array to table	
	 * @return
	 */
	public String[] dataToStringArray() {
		// TODO Auto-generated method stub
		try {
			return new String[]{this.requestId+"",this.infoSystem.getName(),this.dayOfCreation.toString(),this.description};
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * string array to table titles
	 * @return
	 */
	public String[] indexStringArray() 
	{
	      return new String[]{"Request Id","Info System","Date of Creation","Description"};      
	}
	
	
	//// Booleans - status checkers
	/**
	 * ready to evluation
	 * @return true/false
	 */
	 public boolean isEvalReadyForEvaluation()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) && ((sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME ) || 
				                                                             (sStatus == RequestStepStatusEnum.EVL_EVLUATION_EXTENDED )   ||
				                                                             (sStatus == RequestStepStatusEnum.EVL_EVLUATION_EXTENDED_DENY ) ))
		          {
			          return true;
				  }
		  return false;
	 }
	 /**
	  * is request ready for  reevlaution
	  * @return true/false
	  */
	 public boolean isEvalReadyForReEvaluation()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) && ((sStatus == RequestStepStatusEnum.EVL_RETURNED_TO_REVALUTION ) || 
				                                                             (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_EXTENDED ) || 
				                                                             (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_WITH_TIME ) ||
				                                                             ((sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_DENIED) ) ))
				  {
			          return true;
				  }
		  return false;
	 }
	 /**
	  * if request waitnig for time approval
	  * @return
	  */
	 public boolean isEvalTimeWaitingApproval()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) &&
				                                       ((sStatus == RequestStepStatusEnum.EVL_EVLUATION_TIME_EXTENSION_PENDING ) || 
				                                        (sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME_PENDING ) ||
				                                        (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_PENDING) ))
				  {
			          return true;
				  }
		  return false;
	 }
	 /**
	  * has to set time to request
	  * @return boolean
	  */
	 public boolean isEvalTimeToSet()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) &&
                                                        ((sStatus == RequestStepStatusEnum.INILIZED )   ||
				                                       (sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WTIHOUT_TIME ) ||
				                                       ((sStatus == RequestStepStatusEnum.EVL_RETURNED_TO_REVALUTION )) ))
				  {
			          return true;
				  }
		  return false;
	 }
	 /**
	  * is pending reuqest
	  * @return boolean
	  */
	 public boolean isEvalPending()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) &&
				                                       ((sStatus == RequestStepStatusEnum.EVL_EVLUATION_TIME_EXTENSION_PENDING ) || 
				                                        (sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME_PENDING ) ||
				                                        (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_PENDING) ))
				  {
			          return true;
				  }
		  return false;
	 }
	 /**
	  * is requesut open
	  * @return
	  */
	 public boolean isOpen()
	 {
		 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
		  if ( (mStatus != null) && (mStatus == RequestMainStatusEnum.OPEN) )
				  {
			          return true;
				  }
		  return false;
	 }
	 
	 /**
	  * is request in evluation
	  * @return boolean
	  */
	 public boolean isInEvluation()
	 {
		 RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		 
		 if ( (sStatus != null) && (this.isOpen()) && 
                 (
                  (sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME ) ||
                  (sStatus == RequestStepStatusEnum.EVL_EVLUATION_TIME_EXTENSION_PENDING ) ||
                  (sStatus == RequestStepStatusEnum.EVL_EVLUATION_EXTENDED ) ||
                  (sStatus == RequestStepStatusEnum.EVL_EVLUATION_EXTENDED_DENY ) ||
                  (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_EXTENDED ) ||
                  (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_PENDING ) || 
                  (sStatus == RequestStepStatusEnum.EVL_UNVALUATED_WITH_TIME_PENDING ) || 
                  (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_WITH_TIME_PENDING ) || 
                  (sStatus == RequestStepStatusEnum.EVL_REAVLAUTION_TIME_EXTENSION_DENIED) )
                  )
		 	{
			 	return true;
		 	}
		 return false;				
	 }
	 /**
	  * 
	  * @return is in review and decion
	  */
	 public boolean isInReviewAndDecision()
	 {
		 RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		 
		 if ( (sStatus != null) && (this.isOpen()) && 
                 (
                  (sStatus == RequestStepStatusEnum.EVL_PASSED ) ||
                  (sStatus == RequestStepStatusEnum.REV_REVIEWED_TIME_EXTENSION_PENDING ) ||
                  (sStatus == RequestStepStatusEnum.REV_REVIEWED_EXTENDED ) ||
                  (sStatus == RequestStepStatusEnum.REV_REVIEWED_EXTENDED_DENY)
                  ))
		 	{
			 	return true;
		 	}
		 return false;
	 }
	 /**
	  * is in execuation procces
	  * @return
	  */
	 public boolean isInExecuation()
	 {
			
		 RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		 
		 if ( (sStatus != null) && (this.isOpen()) && 
                 (
                  (sStatus == RequestStepStatusEnum.REV_REVIEWED_PASSED ) ||
                  (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_WITH_TIME ) ||
                  (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_TIME_EXTENSION_PENDING ) ||
                  (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_EXTENDED ) ||
                  (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_WTIH_TIME_PENDING ) ||
                  (sStatus == RequestStepStatusEnum.EXE_REXECUTE ) ||
                  (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_EXTENDED_DENY) )
                  )
		 	{
			 	return true;
		 	}
		 return false;
	 }
	/**
	 *  is in testing level
	 * @return
	 */
	 public boolean isInTesting()
	 {
		 RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		 
		 if ( (sStatus != null) && (this.isOpen()) && 
                 (
                  (sStatus == RequestStepStatusEnum.EXE_PASSED ) ||
                  (sStatus == RequestStepStatusEnum.TST_UTESTED_TIME_EXTENSION_PENDING ) ||
                  (sStatus == RequestStepStatusEnum.TST_UTESTED_EXTENDED ) ||
                  (sStatus == RequestStepStatusEnum.TST_UTESTED_EXTENDED_DENY ))
                  )
		 	{
			 	return true;
		 	}
		 return false;
	 }
	 /**
	  * is in closed stage
	  * @return
	  */
	 public boolean isInClose()
	 {
		 RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
		 
		 if ( (sStatus != null) && (this.isOpen()) && 
                 (
                  (sStatus == RequestStepStatusEnum.TST_PASSED ) ||
                  (sStatus == RequestStepStatusEnum.REV_REVIEWED_CLOSE ))
                  )
		 	{
			 	return true;
		 	}
		 return false;	 
	 }
	 
	 
	 


	 	/**
	 	 * is ready for execution
	 	 * @return
	 	 */
	 	 public boolean isReadyForExecution()
		 {
			 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
			  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
			  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) &&
					                                       ((sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_EXTENDED ) || 
					                                        (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_EXTENDED_DENY ) ||
					                                        (sStatus == RequestStepStatusEnum.EXE_REXECUTE ) ||
					                                        (sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_WITH_TIME) ))
					  {
				          return true;
					  }
			  return false;
		 }
	 	 /**
	 	  * is request in exe without time 
	 	  * @return
	 	  */
	 	 public boolean isExecutionwithoutTime()
		 {
			 RequestMainStatusEnum mStatus  = this.getCurrentStatus().getStatus().getmStatus();
			  RequestStepStatusEnum sStatus = this.getCurrentStatus().getStatus().getsStatus();
			  if ( (mStatus != null) && (this.isOpen()) && (sStatus != null) &&
					                                        ((sStatus == RequestStepStatusEnum.EXE_UNEXECUTED_WTIHOUT_TIME) ||
					                                        (sStatus == RequestStepStatusEnum.REV_REVIEWED_PASSED )))
					  {
				          return true;
					  }
			  return false;
		 }
}
